"""回滚"""
import os
from src.core import log
from copy import deepcopy
from src.core import Enums
from sqlalchemy import and_, select
from src.db import dbm, dbs
from src.core.variables.status import *
from .backup_ import Java as Java_backup
from src.core.variables.exception import *
from src.mod import Distribute, safe_remove
from src.core.variables.constant import CONF
from src.schema.hosting import rollback_java_schema
from src.apps.hosting.stater import Jar_manager, Static_manager
from src.core.variables.cls import HOSTING_JAVA_RUNNER_DICT, HOSTING_STATIC_RUNNER_DICT

def _anytime_restore(progress, stype, back_id, schema):
    """随时还原，重部署失败时，自动还原"""

    def cost(func):
        def wrapper(*args, **kwargs):
            nonlocal progress, stype, back_id, schema
            try:
                return func(*args, **kwargs)
            except Exception as e:
                log.ERROR(f"回滚失败：{e}")
                # TODO
                # if progress == 1:
                return ERROR_CODE_CUSTOMIZE(f"回滚失败！", 500)

        return wrapper

    return cost


class __Java:
    # 进度：
    #   0. 无进度
    #   1. 备份当前版本
    #   2. 停止应用
    #   3. 分发到运行池
    #   4. 重新生成runner
    progress = 0
    back_id = None
    schema = None
    stype = Enums.Hosting.Stypes.JAVA

    # @_anytime_restore(progress, stype, back_id, schema)
    def execute(self, schema: rollback_java_schema):
        """执行回滚"""
        from sqlalchemy.orm import scoped_session
        db_session: scoped_session
        restore_app_dict = {}
        self.new_back_id = Java_backup(schema.app_id).current_data().back_id
        self.progress += 1
        old_runner = HOSTING_JAVA_RUNNER_DICT[schema.app_id]
        if old_runner:
            old_runner.stop()
            old_runner.listen_status = False
        self.progress += 1
        with dbm.get("hosting_Java") as db_session:
            stmt = select(dbs.hosting_Java.App).where(dbs.hosting_Java.App.app_id == schema.app_id)
            db_result = db_session.execute(stmt).scalar()
            if db_result:
                db_session.delete(db_result)
                if not dbm.commit(db_session):
                    raise MAIN_EXCEPTION(f"删除旧数据失败！")
                log.INFO(f"删除旧数据成功！")
            else:
                log.WARNING(f"未找到要删除的应用数据: {schema.app_id}")
        with dbm.get("hosting_Java") as db_session:
            stmt = select(dbs.hosting_Java.App_backup).where(dbs.hosting_Java.App_backup.back_id == schema.back_id)
            db_result = db_session.execute(stmt).scalar()
            if db_result:
                restore_app_dict = db_result.__dict__.copy()
                restore_app_dict.pop("_sa__instance_state", None)
                restore_app_dict.pop("_sa_instance_state", None)
                restore_app_dict.pop("back_id", None)
                restore_app_dict['before_id'] = self.new_back_id
                new_app = dbs.hosting_Java.App(**restore_app_dict)
                db_session.add(new_app)
                stmt = select(dbs.hosting_Java.App_backup).where(dbs.hosting_Java.App_backup.before_id == db_result.back_id)
                related_backup = db_session.execute(stmt).scalar()
                if related_backup:
                    related_backup.before_id = db_result.before_id
                if dbm.commit(db_session):
                    self.progress += 1
                    log.INFO(f"移动旧记录成功！")   
                    runner = Jar_manager(schema.app_id)
                    HOSTING_JAVA_RUNNER_DICT[schema.app_id] = runner
                    runner.start()
                    self.progress += 1
                    with dbm.get("hosting_Java") as delete_session:
                        backup_to_delete = (
                            delete_session.query(dbs.hosting_Java.App_backup)
                            .filter(dbs.hosting_Java.App_backup.back_id == schema.back_id)
                            .first()
                        )
                        if backup_to_delete:
                            delete_session.delete(backup_to_delete)
                            if dbm.commit(delete_session):
                                log.INFO(f"删除已恢复的备份记录成功！")
                            else:
                                log.WARNING(f"删除已恢复的备份记录失败！")
                        else:
                            log.WARNING(f"未找到要删除的备份记录: {schema.back_id}")
                    log.INFO(f"回滚成功！")
                    return SUCCESS_CODE_CUSTOMIZE("回滚成功！", 200)
                else:
                    raise MAIN_EXCEPTION(f"移动旧记录失败！")
            else:
                return ERROR_CODE_CUSTOMIZE(f"当前记录不存在！", 500)


java = __Java().execute


class __Static:
    # 进度：
    #   0. 无进度
    #   1. 备份当前版本
    #   2. 禁用应用
    #   3. 分发到运行池
    #   4. 重新生成runner
    progress = 0
    back_id = None
    schema = None
    stype = Enums.Hosting.Stypes.STATIC

    # @_anytime_restore(progress, stype, back_id, schema)
    def execute(self, schema: rollback_java_schema):
        """执行回滚"""
        from sqlalchemy.orm import scoped_session
        db_session: scoped_session
        restore_app_dict = {}
        from .backup_ import Static as Static_backup
        self.new_back_id = Static_backup(schema.app_id).current_data().back_id
        self.progress += 1
        old_runner = HOSTING_STATIC_RUNNER_DICT[schema.app_id]
        if old_runner:
            old_runner.disable()
            old_runner.listen_status = False
        self.progress += 1
        with dbm.get("hosting_Static") as db_session:
            stmt = select(dbs.hosting_Static.App).where(dbs.hosting_Static.App.app_id == schema.app_id)
            db_result = db_session.execute(stmt).scalar()
            if db_result:
                db_session.delete(db_result)
                if not dbm.commit(db_session):
                    raise MAIN_EXCEPTION(f"删除旧数据失败！")
                log.INFO(f"删除旧数据成功！")
            else:
                log.WARNING(f"未找到要删除的应用数据: {schema.app_id}")
        with dbm.get("hosting_Static") as db_session:
            stmt = select(dbs.hosting_Static.App_backup).where(dbs.hosting_Static.App_backup.back_id == schema.back_id)
            db_result = db_session.execute(stmt).scalar()
            if db_result:
                restore_app_dict = db_result.__dict__.copy()
                restore_app_dict.pop("_sa__instance_state", None)
                restore_app_dict.pop("_sa_instance_state", None)
                restore_app_dict.pop("back_id", None)
                restore_app_dict['before_id'] = self.new_back_id
                new_app = dbs.hosting_Static.App(**restore_app_dict)
                db_session.add(new_app)
                stmt = select(dbs.hosting_Static.App_backup).where(dbs.hosting_Static.App_backup.before_id == db_result.back_id)
                related_backup = db_session.execute(stmt).scalar()
                if related_backup:
                    # 修复：正确更新直接后继版本的before_id
                    # 查找直接后继版本并单独更新，而不是批量更新
                    related_backup.before_id = db_result.before_id
                if dbm.commit(db_session):
                    self.progress += 1
                    log.INFO(f"移动旧记录成功！")
                    runner = Static_manager(schema.app_id)
                    HOSTING_STATIC_RUNNER_DICT[schema.app_id] = runner
                    runner.enable()
                    self.progress += 1
                    with dbm.get("hosting_Static") as delete_session:
                        backup_to_delete = (
                            delete_session.query(dbs.hosting_Static.App_backup)
                            .filter(dbs.hosting_Static.App_backup.back_id == schema.back_id)
                            .first()
                        )
                        if backup_to_delete:
                            delete_session.delete(backup_to_delete)
                            if dbm.commit(delete_session):
                                log.INFO(f"删除已恢复的备份记录成功！")
                            else:
                                log.WARNING(f"删除已恢复的备份记录失败！")
                        else:
                            log.WARNING(f"未找到要删除的备份记录: {schema.back_id}")
                    log.INFO(f"回滚成功！")
                    return SUCCESS_CODE_CUSTOMIZE("回滚成功！", 200)
                else:
                    raise MAIN_EXCEPTION(f"移动旧记录失败！")
            else:
                return ERROR_CODE_CUSTOMIZE(f"当前记录不存在！", 500)


static = __Static().execute

